#ifndef __context_kenny_ojifwoeeif9w23__
#define __context_kenny_ojifwoeeif9w23__

#include <atomic>
#include <array>
#include <future>
#include <mutex>

#include <hude/base/base_type.hpp>
#include <hude/base/optional.hpp>
#include <hude/base/hex.hpp>
#include <hude/base/async.hpp>
#include <hude/aio/epoll.hpp>

#if ( defined( _WIN32 ) || defined( _WIN64 ) ) && !defined( USING_HUDE_AIO_SELECT )
#  define USING_HUDE_AIO_SELECT
#endif

namespace hude
{
    namespace aio
    {
        /*********************************************************************
         * @brief 轻量级用户态互斥锁
         */
        struct tinylock_t
        {
            using auto_t = std::lock_guard< tinylock_t >;

            mutable std::atomic_flag lock_;

            tinylock_t() : lock_( false ) {}
            ~tinylock_t() { lock_.clear(); }

            bool try_lock() const { return false == lock_.test_and_set(); }
            void lock() const { while( lock_.test_and_set() ); }
            void unlock() const { lock_.clear(); }
        };

        /*********************************************************************
         * @brief 异步IO上下文使用的最大EPOLL监听数
         */
        enum : std::size_t { emDEFAULT_MAX_EPOLL = 64U };

        /*********************************************************************
         * @brief 默认的异步模型
         */
    #ifdef USING_HUDE_AIO_SELECT
        template< typename _user, std::size_t _count, typename _mutex = std::recursive_mutex >
        using _default_poller_t = hude::aio::select_plus_t< _user, _count, _mutex >;
    #else
        template< typename _user, std::size_t _count, typename _mutex = std::mutex >
        using _default_poller_t = hude::aio::epoll_plus_t< _user, _count, _mutex >;
    #endif

        /*********************************************************************
         * @brief 异步IO事件类型
         */
        using evt_type_t = epoll_evt_t;

        /*********************************************************************
         * @brief 异步IO上下文
         */
        template< std::size_t _count = emDEFAULT_MAX_EPOLL, typename _user = hude::any_t,
            typename _poll = _default_poller_t< _user, _count > >
        class context_t :
            public std::enable_shared_from_this< context_t< _count > >
        {
        public:
            //----------------------------------------------------------------------
            enum : std::size_t { emCOUNT = _count };

            //----------------------------------------------------------------------
            using this_t     = context_t< _count, _user, _poll >;
            using user_t     = _user;
            using tasks_t    = hude::async_t;
            using loop_t     = _poll;
            using handler_t  = int;
            using on_exit_t  = std::function< void( handler_t, user_t& ) >;

        public:
            //----------------------------------------------------------------------
            // 构造函数可设备退出回调，在上下文退出时告知每个事件关注者
            context_t( on_exit_t on_exit = on_exit_t{}, std::shared_ptr< async_t > tasks = std::shared_ptr< async_t >{ nullptr } ) :
                tasks_( tasks ), on_exit_( on_exit ), running_( false )
            {
                socket_initer_t::get_obj();

                if( !tasks_ )
                {
                    tasks_ = hude::async_t::get_default_ptr();
                }
            }

            //----------------------------------------------------------------------
            ~context_t()
            {
            }

            //----------------------------------------------------------------------
            // 加入一个事件关注者
            inline int evt_commit( handler_t handler, typename loop_t::cb_event_t cb,
                typename loop_t::user_t user = typename loop_t::user_t{},
                uint32_t events = aio::epoll_evt_t::emEPOLLET | aio::epoll_evt_t::emEPOLLIN )
            {
                return loop_.add( handler, cb, user, events );
            }

            //----------------------------------------------------------------------
            // 删除某个事件关注者
            inline int evt_remove( handler_t handler )
            {
                return loop_.del( handler);
            }

            //----------------------------------------------------------------------
            // 删除all事件关注者
            inline void evt_clean()
            {
                this->_evt_clear();
            }

            //----------------------------------------------------------------------
            // 如果需要指定任务ID，可从此函数获得ID
            inline typename tasks_t::id_t task_genid()
            {
                return tasks_->id();
            }

            //----------------------------------------------------------------------
            // 提交一个需要异步执行的任务
            inline bool task_commit( std::function< void() > cb )
            {
                return tasks_->add( cb );
            }

            //----------------------------------------------------------------------
            // 提交一个需要异步执行的任务
            inline hude::optional_t< typename tasks_t::id_t >
            task_commit( std::function< void() > cb, std::size_t timeout )
            {
                auto _cb = []( std::function< void() > cb, typename tasks_t::id_t, uintptr_t ) { cb(); };

                auto id = tasks_t::id();

                auto ret = tasks_->add( id, tasks_t::emTYPE_SINGLE, typename tasks_t::interval_t( timeout ),
                    std::bind( _cb, cb, std::placeholders::_1, std::placeholders::_2 ) );

                return ret? id : hude::optional_t< typename tasks_t::id_t >{};
            }

            //----------------------------------------------------------------------
            // 提交一个需要定时执行的任务
            inline hude::optional_t< typename tasks_t::id_t >
            task_commit( std::function< void( uintptr_t, uintptr_t ) > cb, std::size_t timeout, uintptr_t user )
            {
                auto id = tasks_t::id();

                auto ret = tasks_->add( id, tasks_t::emTYPE_CYCLICITY, typename tasks_t::interval_t( timeout ), cb, user );

                return ret? id : hude::optional_t< typename tasks_t::id_t >{};
            }

            //----------------------------------------------------------------------
            // 提交一个需要定时执行的任务
            inline bool task_commit( typename tasks_t::id_t id, uint8_t type, typename tasks_t::interval_t timeout,
                typename tasks_t::on_timer_t on_timer, uintptr_t user = 0U )
            {
                return tasks_->add( id, type, timeout, on_timer, user );
            }

            //----------------------------------------------------------------------
            // 删除一个在队列中的等待执行的异步任务
            inline bool task_remove( typename tasks_t::id_t id )
            {
                return tasks_->remove( id );
            }

            //----------------------------------------------------------------------
            // 清除队列中的等待执行的异步任务
            inline void task_clean()
            {
                tasks_->clean();
            }

            //----------------------------------------------------------------------
            // 取消上下文的工作并退出
            inline void cancel()
            {
                running_ = false;
            }

            //----------------------------------------------------------------------
            // 获得上下文异常退出的错误信息
            inline const char* error() const
            {
                static hude::format_t fmt;

                int err = errno;

                fmt( "err( %d ): %s", err, strerror( err ) );

                return fmt.str().c_str();
            }

            //----------------------------------------------------------------------
            // 阻塞模式启动上下文的事件泵和任务池
            inline int run( std::function< void() > cb_entry, std::size_t timeout = 500U, bool keep = true )
            {
                return this->_run( cb_entry, timeout, keep );
            }

            //----------------------------------------------------------------------
            // 异步模式启动上下文的事件泵和任务池
            inline void boot( std::function< void() > cb_entry, std::size_t timeout = 500U, bool keep = true )
            {
                if( running_ )
                {
                    cb_entry(); return;
                }

                std::promise< void > pe;

                auto cb_entry_addition = [=, &pe]()
                {
                    cb_entry();

                    pe.set_value();
                };

                auto cb_run = [=]( std::function< void() > cb_entry, std::size_t timeout, bool keep )
                {
                    this->_run( cb_entry, timeout, keep );
                };

                std::thread( [=]() { cb_run( cb_entry_addition, timeout, keep ); } ).detach();

                pe.get_future().get();
            }

            //----------------------------------------------------------------------
            // 返回任务池对象
            inline std::shared_ptr< async_t > tasks()
            {
                return tasks_;
            }

            //----------------------------------------------------------------------
            // 返回异步IO泵对象
            inline loop_t& loop()
            {
                return loop_;
            }

            //----------------------------------------------------------------------
            // 返回运行状态
            inline bool running() const
            {
                return running_;
            }

        public:
            //----------------------------------------------------------------------
            // 实例化一个上下文
            static inline std::shared_ptr< this_t > aio()
            {
                static std::shared_ptr< this_t > context{ []{ return new this_t; }() };

                return context;
            }

            //----------------------------------------------------------------------
            // 实例化一个上下文
            static inline std::shared_ptr< this_t > ctx()
            {
                return aio();
            }

            //----------------------------------------------------------------------
            // 实例化一个上下文，并且阻塞模式启动上下文的事件泵和任务池
            static inline std::shared_ptr< this_t > ctx_and_boot(
                std::function< void() > cb_entry = std::function< void() >{}, std::size_t timeout = 200U, bool keep = true )
            {
                auto ptr = ctx();

                ptr->boot(  cb_entry, timeout, keep );

                return ptr;
            }

        private:
            //----------------------------------------------------------------------
            void _evt_clear()
            {
                if( this->on_exit_ ) 
                {
                    auto cb = [=]( handler_t key, typename loop_t::item_t& item ) -> bool
                    {
                        this->on_exit_( key, std::get<1>( item ) ); return true;
                    };

                    loop_.foreach( cb );
                }

                loop_.clear();
            }

            //----------------------------------------------------------------------
            int _run( std::function< void() > cb_entry, std::size_t timeout, bool keep )
            {
                if( running_ == true ) return -100;

                // 初始化
                running_ = true;

                int ret = 0;

                if( ! loop_.create() )
                    return -101;

                cb_entry();

                // 工作循环
                while( running_ && ( keep || ! loop_.empty() ) )
                {
                    ret = loop_.wait( timeout );
                    if( ret < 0 && errno != EINTR ) break;
                }

                loop_.close();

                // 退出清理
                running_ = false;

                this->_evt_clear();

                return ret;
            }

        private:
            //----------------------------------------------------------------------
            loop_t                      loop_;
            std::shared_ptr< tasks_t >  tasks_;
            on_exit_t                   on_exit_;
            std::atomic_bool            running_;

        };

        /*********************************************************************
         * @brief 异步IO上下文
         */
        template< std::size_t _count = emDEFAULT_MAX_EPOLL, typename _user = hude::any_t,
            typename _poll = _default_poller_t< _user, _count > >
        using ctx_t = std::shared_ptr< context_t< _count, _user, _poll > >;

        template< std::size_t _count = emDEFAULT_MAX_EPOLL, typename _user = hude::any_t,
            typename _poll = _default_poller_t< _user, _count > >
        using aio_t = std::shared_ptr< context_t< _count, _user, _poll > >;

        /*********************************************************************
         * @brief 端对端异步通信
         */
        namespace e2e
        {
            /*********************************************************************
             * @brief 端点接口
             */
            struct _peer_t
            {
                using handle_t = int;
                using peer_t = std::shared_ptr< _peer_t >;

                virtual ~_peer_t() {}

                virtual int send( const void*, size_t ) = 0;
                virtual int recv( void*, size_t ) = 0;

                virtual handle_t native() const = 0;

                virtual void close() = 0;
            };

            /*********************************************************************
             * @brief 端到端绑定
             */
            class _bind_t
            {
            public:
                enum : uint32_t
                { 
                    emIN     = hude::aio::epoll_evt_t::emEPOLLIN,
                    emHUP    = hude::aio::epoll_evt_t::emEPOLLHUP,
                    emERR    = hude::aio::epoll_evt_t::emEPOLLERR
                };

                using peer_t = _peer_t::peer_t;
                using cb_filter_t = std::function< void( std::vector<uint8_t>& ) >;

            public:
                _bind_t( peer_t a, peer_t b ) : a_( a ), b_( b ) {}

                template< std::size_t _count, typename _user, typename _poll >
                void bind( aio_t< _count, _user, _poll > aio, cb_filter_t filter = cb_filter_t{}, size_t siz = 255U )
                {
                    auto cb_evt = [=]( peer_t src, peer_t dst, uint32_t evts, hude::any_t& )
                    {
                        log_nte( "aio event %#010x, src: %d", evts, src->native() );

                        // 可读事件
                        if( evts & emIN )
                        {
                            hude::buffer_t buffer( siz );

                            auto ret = src->recv( &buffer[0], siz );

                            if( ret > 0 )
                            {
                                buffer.resize( ret );

                                if( filter ) filter( buffer );

                                if( ! buffer.empty() ) dst->send( &(buffer[0]), siz );
                            }
                        }

                        // 挂断事件和错误事件
                        if( evts & ( emHUP | emERR ) )
                        {
                            this->unbind( aio );

                            src->close();
                        }
                    };

                    aio->evt_commit( a_->native(), std::bind( cb_evt, a_, b_, std::placeholders::_1, std::placeholders::_2 ) );
                    aio->evt_commit( b_->native(), std::bind( cb_evt, b_, a_, std::placeholders::_1, std::placeholders::_2 ) );
                }

                template< std::size_t _count, typename _user, typename _poll >
                void unbind( aio_t< _count, _user, _poll > aio )
                {
                    aio->evt_remove( a_->native() );
                    aio->evt_remove( b_->native() );
                }

            private:
                _peer_t::peer_t a_, b_;
            };
        } //namespace p2p

    } //namespace aio
} //namespace hude

#endif //__context_kenny_ojifwoeeif9w23__
